
#include "RealTimeClock.h"

#define BCD2Val(bcd)	(((bcd)>> 4)  * 10 + ((bcd) & 0x0F))
#define Val2BCD(val)	((((val) / 10) << 4)|((val) %10))

static const RealTimeClock* realClock;

static void RealTimeClock_BCD2Tm(TimeBCD* bcdTime, struct tm_s* tm){
	bcdTime->bcd_hour &= 0x3F;
	
	tm->tm_sec = BCD2Val(bcdTime->bcd_sec);
	tm->tm_min = BCD2Val(bcdTime->bcd_min);
	tm->tm_hour = BCD2Val(bcdTime->bcd_hour);
	tm->tm_wday = bcdTime->bcd_wday;
	tm->tm_mday = BCD2Val(bcdTime->bcd_mday);
	tm->tm_mon = BCD2Val(bcdTime->bcd_mon);
	tm->tm_year = BCD2Val(bcdTime->bcd_year) + 2000;
}

static void RealTimeClock_Tm2BCD(struct tm_s* tm, TimeBCD* bcdTime){
	bcdTime->bcd_sec = Val2BCD(tm->tm_sec);
	bcdTime->bcd_min = Val2BCD(tm->tm_min);
	bcdTime->bcd_hour = Val2BCD(tm->tm_hour);
	bcdTime->bcd_wday = tm->tm_wday;
	bcdTime->bcd_mday = Val2BCD(tm->tm_mday);
	bcdTime->bcd_mon = Val2BCD(tm->tm_mon);
	uint8_t year = tm->tm_year - 2000;
	bcdTime->bcd_year = Val2BCD(year);
}


void RealTimeClock_Register(const RealTimeClock* clock){
	if(clock){
		realClock = clock;
	}
}
void RealTimeClock_Set(struct tm_s *tim){
	if(realClock && realClock->set){
		realClock->set(tim);
	}
	else{
		TimeBCD bcdTime;
		RealTimeClock_Tm2BCD(tim, &bcdTime);
		RealTimeClock_SetBCD(&bcdTime);
	}
}
void RealTimeClock_Get(struct tm_s *tim){
	if(realClock && realClock->get){
		realClock->get(tim);
	}
	else{
		TimeBCD bcdTime;
		RealTimeClock_GetBCD(&bcdTime);
		RealTimeClock_BCD2Tm(&bcdTime, tim);
	}
}

void RealTimeClock_GetBCD(TimeBCD * tim_bcd){
	if(realClock && realClock->getBcd){
		realClock->getBcd(tim_bcd);
	}
}

void RealTimeClock_SetBCD(TimeBCD * tim_bcd){
	if(realClock && realClock->setBcd){
		realClock->setBcd(tim_bcd);
	}
}

void RealTimeClock_SetTime(uint32_t time){
	struct tm_s tm;
	fun_localtime(&tm, time);
	RealTimeClock_Set(&tm);
}

uint32_t RealTimeClock_Now(void){
	struct tm_s current;
	RealTimeClock_Get(&current);
	return fun_mktime(&current);
}

